package com.sakura.oj.controller;

import com.sakura.oj.common.BaseResponse;
import com.sakura.oj.common.ErrorCode;
import com.sakura.oj.common.ResultUtils;
import com.sakura.oj.exception.BusinessException;
import com.sakura.oj.model.dto.submit.DailySubmitStatQuery;
import com.sakura.oj.model.entity.User;
import com.sakura.oj.model.vo.DailySubmissionStat;
import com.sakura.oj.model.vo.HotProblemVo;
import com.sakura.oj.model.vo.UserRankVo;
import com.sakura.oj.service.ProblemService;
import com.sakura.oj.service.ProblemSubmitService;
import com.sakura.oj.service.UserService;
import com.sakura.oj.utils.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.Min;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 统计接口
 */
@RestController
@RequestMapping("statistic")
@RequiredArgsConstructor
public class StatisticsController {

    private final ProblemService problemService;
    private final ProblemSubmitService problemSubmitService;
    private final UserService userService;

    // 使用构造函数注入

    /**
     * 获取提交统计信息
     *
     * @param form {@link DailySubmitStatQuery}
     * @return {@link BaseResponse}<{@link List < DailySubmissionStat >}>
     */
    @GetMapping("submission-stats")
    public BaseResponse<List<DailySubmissionStat>> getSubmissionStats(DailySubmitStatQuery form) {
        Long userId = UserHolder.getUserId();
        String period = form.getPeriod();
        String startDateStr = form.getStartDate();
        String endDateStr = form.getEndDate();

        LocalDate startDate = null;
        if (StringUtils.hasText(startDateStr)) {
            startDate = LocalDate.parse(form.getStartDate());
        }
        LocalDate endDate = null;
        if (StringUtils.hasText(endDateStr)) {
            endDate = LocalDate.parse(form.getEndDate()).plusDays(1);
        }

        if (StringUtils.hasText(period)) {
            if ("pastYear".equals(period)) {
                // 获取过去一年的提交统计信息
                startDate = LocalDate.now().minusYears(1);
                // 比今天多一天，因为LocalDate.now()获取的是当天的日期，所以需要加一天
                endDate = LocalDate.now().plusDays(1);
            } else {
                // 判断是否为年份数值
                try {
                    int year = Integer.parseInt(period);
                    // year的1月1 开始 到 year 的 12月31日
                    if (year < 1970 || year > LocalDate.now().getYear()) {
                        throw new BusinessException(ErrorCode.PARAMS_ERROR, "period参数格式错误");
                    }
                    startDate = LocalDate.of(year, 1, 1);
                    endDate = LocalDate.of(year, 12, 31);
                } catch (NumberFormatException e) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "period参数格式错误");
                }
            }
        }
        List<DailySubmissionStat> problemSubmitVos = problemSubmitService.getSubmissionStats(userId, startDate, endDate);
        return ResultUtils.success(problemSubmitVos);
    }

    /**
     * 获取积分排行榜
     */
    @GetMapping("score-rank")
    public BaseResponse<List<UserRankVo>> getScoreRank(@RequestParam(value = "pageSize") Long pageSize) {
        if (pageSize == null) {
            pageSize = 5L;
        }
        if (pageSize > 20) {
            pageSize = 20L;
        }
        List<UserRankVo> userRankVos = problemSubmitService.getScoreRank(pageSize);
        // 渲染排名
        List<Long> userIds = new ArrayList<>(userRankVos.size() + 1);
        userRankVos.forEach(userRankVo -> {
            userRankVo.setRank(userRankVos.indexOf(userRankVo) + 1);
            userIds.add(userRankVo.getUserId());
        });
        // 绑定username
        List<User> users = userService.listByIds(userIds);
        Map<Long, String> userMap = users.stream().collect(Collectors.toMap(User::getId, User::getUserName));
        userRankVos.forEach(userRankVo -> userRankVo.setUsername(userMap.get(userRankVo.getUserId())));
        return ResultUtils.success(userRankVos);
    }

    /**
     * 热门题目
     */
    @GetMapping("hot-problems")
    @Validated
    public BaseResponse<List<HotProblemVo>> getHotProblems(@RequestParam(value = "periodDays", defaultValue = "7") @Min(value = 1, message = "参数传递错误") Long periodDays,
                                                           @RequestParam(value = "limit", defaultValue = "5") @Min(value = 1, message = "参数传递错误") Long limit) {
        if (periodDays > 30) {
            periodDays = 30L;
        }
        if (limit > 20) {
            limit = 20L;
        }
        List<Long> hotProblemIds = problemSubmitService.getHotProblemIds(periodDays, limit);

        List<HotProblemVo> hotProblemVos = problemService.getHotProblems(hotProblemIds);

        return ResultUtils.success(hotProblemVos);
    }
}
